package com.bfb;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.bfb.helpers.ServerUtilities;

public class Details extends Activity implements OnRatingBarChangeListener {

	static final String PATH = "/filter/dish_detail";
	// static final String SERVER = "10.0.2.2:8080";
	TextView name, location, ing, comms, raters, newCom;
	TextView comments;
	RatingBar rate;
	Button addcommet;
	ImageView img;
	String loca_key; // the restaurant location key
	String loca_name; // the restaurant name
	Float f;
	int no_rate, z = 0;
	DefaultHttpClient CLIENT;
	String id, rate_value, dishtype_name, dishtype_id;
	String imgString;
	boolean rated = false;
	StringBuilder comString = new StringBuilder();
	// String[] comarr;
	ArrayList<String> comarr;
	boolean commented = false;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.details);
		CLIENT = new DefaultHttpClient();
		raters = (TextView) findViewById(R.id.raters);
		name = (TextView) findViewById(R.id.Dish_name);
		location = (TextView) findViewById(R.id.Dish_Location);
		ing = (TextView) findViewById(R.id.Dish_ing);
		rate = (RatingBar) findViewById(R.id.ratingbar);
		img = (ImageView) findViewById(R.id.Dish_image);
		comments = (TextView) findViewById(R.id.Dish_comm);
		addcommet = (Button) findViewById(R.id.add_comment);

		Log.e("details", "IN Details");
		Bundle extras = getIntent().getExtras();
		if (extras == null) {
			return;
		}
		id = extras.getString("Key");
		rate.setOnRatingBarChangeListener(this);
		new DishDetail().execute();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.dish_details_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		if (item.getItemId() == R.id.add_to_favorites_menuItem) {
			if (!Main.user.likesDishByKey(id)) {
				ServerUtilities.background(new Runnable() {
					@Override
					public void run() {
						String input = "";
						try {
							HttpClient httpclient = new DefaultHttpClient();
							HttpPost httppost = new HttpPost("http://"
									+ Main.SERVER + "/user_info/add_fav_dishes");
							List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
									2);

							nameValuePairs.add(new BasicNameValuePair("userId",
									Main.android_id));
							nameValuePairs
									.add(new BasicNameValuePair("key", id));

							httppost.setEntity(new UrlEncodedFormEntity(
									nameValuePairs));

							// Execute HTTP Post Request
							HttpResponse response = httpclient
									.execute(httppost);

							/* Checking response */
							if (response != null) {
								HttpEntity entity = response.getEntity();

								// input = getContent(entity);
								input = ServerUtilities
										.getContentFromStream(entity
												.getContent());
								if (input.equals("Dish added successfully")) {
									String dishName = name.getText().toString();
									Bitmap bitmap = ((BitmapDrawable) img
											.getDrawable()).getBitmap();

									Main.user.addToFavorites(dishName, id,
											bitmap);
								} else {
									runOnUiThread(new Runnable() {

										@Override
										public void run() {
											Toast.makeText(
													getBaseContext(),
													getString(R.string.addToFavoritesError),
													Toast.LENGTH_LONG).show();
										}
									});
								}
								Log.e("input", input);

							}
						} catch (Exception e) {
							Log.e("Exception", e.getMessage());
							Log.e("input in catch", input);
							runOnUiThread(new Runnable() {

								@Override
								public void run() {
									Toast.makeText(
											getBaseContext(),
											getString(R.string.addToFavoritesError),
											Toast.LENGTH_LONG).show();
								}
							});
						}

					}

				});
			} else {
				Toast.makeText(getBaseContext(),
						getString(R.string.alreadyAFav), Toast.LENGTH_SHORT)
						.show();
			}
		} else {
			/**
			 * This is where the action to be performed when the user clicks on
			 * the "Play with this Dish" from the menu of any detailed view of a
			 * dish. This will start a new Intent and sends the ingredients and
			 * dish type and id to the GameActivity to load the ingredients in
			 * the game and play around with them.
			 * 
			 * @author Rawan Khalil(rawan.tkhalil@gmail.com)
			 */
			if (item.getItemId() == R.id.customize_dish_menuItem) {
				Intent customizeInGameIntent = new Intent(getBaseContext(),
						GameActivity.class);
				customizeInGameIntent.putExtra("ingredients", ing.getText());
				customizeInGameIntent.putExtra("dishTypeName", dishtype_name);
				customizeInGameIntent.putExtra("dishTypeKey", dishtype_id);
				customizeInGameIntent.putExtra("customize", true);
				startActivity(customizeInGameIntent);
				finish();
			}
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * If the user changes the rate the DishDetail asynTask is executed by
	 * setting the rated flag to true to send the server the new value and get
	 * the total average
	 */
	@Override
	public void onRatingChanged(RatingBar ratingBar, float rating,
			boolean fromUser) {
		Log.e("Rate", "Changed Rating");
		if (rated) {
			Log.e("Rate", "Changed Rating 2222222");
			rate_value = rating + "";
			new DishDetail().execute();
		}

		/*
		 * float n=(f+rating)/(no_rate+1); final String rval=n+""; final String
		 * key=id; final float Rating = rating; ServerUtilities.background(new
		 * Runnable() { public void run() { try {
		 * 
		 * List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
		 * nameValuePairs.add(new BasicNameValuePair("dish", key));
		 * nameValuePairs.add(new BasicNameValuePair("rvalue", rval));
		 * nameValuePairs.add(new BasicNameValuePair("id", Main.android_id));
		 * URI uri = URIUtils.createURI("http", Main.SERVER, -1, "/func/rate",
		 * URLEncodedUtils.format(nameValuePairs, "UTF-8"), null); HttpGet
		 * httpget = new HttpGet(uri); Log.e("Details2",
		 * httpget.getURI().toString()); HttpResponse resp =
		 * CLIENT.execute(httpget); StatusLine statusLine =
		 * resp.getStatusLine(); int statusCode = statusLine.getStatusCode();
		 * Log.e("rating",statusCode+""); StringBuilder respStr = new
		 * StringBuilder(); if(statusCode==200){
		 * Log.e("Load JSON","Success Rate"); HttpEntity entity =
		 * resp.getEntity(); InputStream content = entity.getContent();
		 * BufferedReader reader = new BufferedReader( new
		 * InputStreamReader(content)); String line; while ((line =
		 * reader.readLine()) != null) { respStr.append(line); }
		 * Log.e("rate",respStr.toString()); JSONObject jsonObject = new
		 * JSONObject(respStr.toString());
		 * Rating=(float)jsonObject.getDouble("average"); int raters =
		 * jsonObject.getInt("num"); } else
		 * Log.e("Load JSON","Failed to download file"); } catch (Exception e) {
		 * Log.e("Details", e.getMessage(), e);
		 * 
		 * } } }); rate.setRating(Rating);
		 */
	}

	public void MapView(View v1) {
		// loca_key is the attribute containing the restaurant key
		Intent intent = new Intent(Details.this, MapViewActivity.class);
		intent.putExtra("loca_key", loca_key);
		intent.putExtra("loca_name", loca_name);
		startActivity(intent);
	}

	void print(ArrayList<String> a) {
		for (int i = 0; i < a.size(); i++) {
			Log.e("comments are", a.get(i).toString());
		}
	}

	public void errorInDialogBefore(String s) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(s)
				.setCancelable(false)
				.setPositiveButton(this.getResources().getString(R.string.ok),
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int id) {

							}
						});
		AlertDialog alert = builder.create();
		alert.show();
	}

	/**
	 * 
	 * @param v
	 *            current view
	 * 
	 *            This method is called when the user press the add comment
	 *            button. It creates an empty dialog for the user to enter the
	 *            comment in. If the user Adds a comment the DishDetail asynTask
	 *            is executed by setting the commented flag to true to send the
	 *            server the comment to be added to the list of comments on the
	 *            view dish. If the user entered an empty comment or a comment
	 *            that has been entered before, he is notified by another dialog
	 *            called through this method:
	 *            {@link Details#errorInDialogBefore(String)}
	 * 
	 * @author Hadeer Diwan (hadeer.diwan@gmail.com)
	 */
	public void InsertComment(View v) {

		final String writtenBefore = this.getResources().getString(
				R.string.writtenBefore);
		final String empty = this.getResources().getString(
				R.string.emptyComment);
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		alert.setTitle("New Comment");
		final EditText input = new EditText(this);
		input.setLines(1);
		alert.setView(input);

		alert.setNegativeButton(this.getResources().getString(R.string.ok),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int whichButton) {
						Editable value = input.getText();
						DishDetail d = new DishDetail();

						if (!value.toString().equals("")
								&& !comarr.contains(value.toString().trim())
								&& !value.toString().equals(" ")) {
							comarr.add(value.toString());
							comString.append(value.toString().trim());
							/*ArrayAdapter<String> adapter = new ArrayAdapter<String>(
									getApplicationContext(),
									R.layout.list_row_item, comarr);
							comments.setAdapter(adapter);*/
							//comments.setText(comString);
							commented = true;
							rated = false;
							new DishDetail().execute();
						} else if (comarr.contains(value.toString())) {
							errorInDialogBefore(writtenBefore);
						} else
							errorInDialogBefore(empty);

					}
				});

		alert.setPositiveButton("Cancel",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int whichButton) {

					}
				});
		alert.show();

	}

	/**
	 * The DishDetails is the asyncTask responsible of doing 2 things either to
	 * get the details of a dish and this executed once the intent is fired from
	 * the previous activity the other thing it does is when the user rates it
	 * sends the rate value and the user device id to server to add the rating
	 * or edit it if the user rated before.
	 * 
	 * @author salma
	 * 
	 */
	class DishDetail extends AsyncTask<Void, Void, String> {

		private ProgressDialog pdia;

		@Override
		protected void onPreExecute() {
			if (rated)
				pdia = ProgressDialog.show(Details.this, "",
						"Sending your Rate...", true);
			else
				pdia = ProgressDialog.show(Details.this, "",
						"Loading Dish Details...", true);
		}

		@Override
		public void onCancelled() {
			pdia.dismiss();
		}

		@Override
		protected void onPostExecute(String result) {
			comString = new StringBuilder();
			Log.i("In Thread", "end loading");
			pdia.dismiss();
			try {
				Log.e("jsonArray", "extract Json");
				Log.e("jsonArrayResult", result.toString());
				if (rated) {
					Log.e("Post Rate", "Enter Rating");
					JSONObject jsonObject = new JSONObject(result.toString());
					f = (float) jsonObject.getDouble("average");
					Log.e("Post Rate", "Enter Rating1");
					int num_rater = jsonObject.getInt("num");
					raters.setText("Number of raters: " + num_rater);
					Log.e("Post Rate", "Enter Rating2");
					rated = false;
				} else {
					JSONArray jsonArray = new JSONArray(result.toString());

					JSONObject jsonObject = jsonArray.getJSONObject(0);
					// Log.i("jsonArray", jsonObject.getString("name"));
					name.setText(jsonObject.getString("name"));
					location.setText(jsonObject.getString("loca_name"));
					f = new Float(jsonObject.getString("rate"));
					no_rate = new Integer(jsonObject.getString("rate_num"));
					raters.setText(getString(R.string.details_rating) + " "
							+ no_rate);
					loca_key = jsonObject.getString("loca_key");
					loca_name = jsonObject.getString("loca_name");
					dishtype_id = jsonObject.getString("dishtype_key");
					dishtype_name = jsonObject.getString("dishtype_name");
					Bitmap b = BitmapFactory
							.decodeStream(new ByteArrayInputStream(Base64
									.decode(jsonObject.getString("img"),
											Base64.DEFAULT)));

					imgString = jsonObject.getString("img");
					img.setImageBitmap(Bitmap.createScaledBitmap(b, 300, 200,
							true));
					// img.setImageBitmap(b);

					JSONArray j_ing = jsonObject.getJSONArray("ing");
					JSONArray j_com = jsonObject.getJSONArray("com");
					String ingString = "";
					// String comString="";
					// String[] comarr = new String[j_com.length()];
					comarr = new ArrayList<String>();
					for (int j = 0; j < j_ing.length(); j++)
						if (j == j_ing.length() - 1)
							ingString += j_ing.getString(j);
						else
							ingString += j_ing.getString(j) + ", ";

					for (int j = 0; j < j_com.length(); j++)
						if (j == j_com.length() - 1) {
							comString.append(j_com.getString(j) + "\n");
							// comarr[j]=j_com.getString(j);
							comarr.add(j, j_com.getString(j));
						} else {
							comString.append(j_com.getString(j) + "\n");
							// comarr[j]=j_com.getString(j);
							comarr.add(j, j_com.getString(j));
						}
					/*ArrayAdapter<String> adapter = new ArrayAdapter<String>(
							getApplicationContext(), R.layout.list_row_item,
							comarr);*/
					//comments.setAdapter(adapter);
					 comments.setText(comString);
					ing.setText(ingString);
					Log.e("comments", comString.toString());
				}
				rate.setRating(f);
				rated = true;
			} catch (Exception e) {
				Log.e("jsonArray", e.getMessage(), e);
			}

		}

		/**
		 * If the user enters a new comment the new comment is added to lost of
		 * comments of the dish and a post is made on the server with the
		 * comment added.
		 * 
		 * @auther Hadeer Diwan(hadeer.diwan@gmail.com)
		 */
		@Override
		protected String doInBackground(Void... params) {
			final StringBuilder respStr = new StringBuilder();
			HttpResponse resp;
			try {
				if (commented) {
					List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
							2);
					nameValuePairs.add(new BasicNameValuePair("dish", id));
					nameValuePairs.add(new BasicNameValuePair("comment",
							comString.toString()));

					String url = "http://" + Main.SERVER + "/func/comment";
					HttpPost request = new HttpPost(url);
					request.setEntity(new UrlEncodedFormEntity(nameValuePairs));

					Log.e("commenting", request.getURI().toString());
					resp = CLIENT.execute(request);
					// resp = CLIENT.execute(httpget);

				}
				if (rated) {
					List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
							3);
					nameValuePairs.add(new BasicNameValuePair("dish", id));
					nameValuePairs.add(new BasicNameValuePair("rvalue",
							rate_value + ""));
					nameValuePairs.add(new BasicNameValuePair("id",
							Main.android_id));
					String url = "http://" + Main.SERVER + "/func/rate";
					HttpPost request = new HttpPost(url);
					request.setEntity(new UrlEncodedFormEntity(nameValuePairs));

					Log.e("Rating", request.getURI().toString());
					resp = CLIENT.execute(request);

				}

				else {
					List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
							1);
					nameValuePairs.add(new BasicNameValuePair("id", id));
					URI uri = URIUtils.createURI("http", Main.SERVER, -1, PATH,
							URLEncodedUtils.format(nameValuePairs, "UTF-8"),
							null);
					HttpGet httpget = new HttpGet(uri);
					// post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
					resp = CLIENT.execute(httpget);
					Log.e("Details", httpget.getURI().toString());
				}

				StatusLine statusLine = resp.getStatusLine();
				int statusCode = statusLine.getStatusCode();
				Log.e("Status Code", statusCode + "");
				if (statusCode == 200) {
					Log.e("Details2", respStr.toString());
					HttpEntity entity = resp.getEntity();
					InputStream content = entity.getContent();
					BufferedReader reader = new BufferedReader(
							new InputStreamReader(content));
					String line;
					while ((line = reader.readLine()) != null) {
						respStr.append(line);
					}

				} else
					Log.e("Load JSON", "Failed to download file");
			} catch (Exception e) {
				Log.e("Details", e.getMessage(), e);
			}

			return respStr.toString();
		}

	}

}